// Land.h: interface for the Land class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(LAND_H)
#define LAND_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/* PLIB includes */
#include <plib/ul.h>
#include <plib/sg.h>
#include <plib/ssg.h>
//#include <plib/ssgAux.h>

/* Project class includes */
#include "Defines.h"
#include "BMPImage.h"
#include "LoadingInfo.h"

#define SUPER_SPEED 0
//#define LOW_SPEED 1

#define DEF_TERRAIN 0
//#define TRY_TERRAIN 1

#define LAND_FILENAME_STRING_LENGTH 1024
#define FILE_ROW_STRING_LENGTH      1024

#define LAND_TRIANGLE_GRID_SIZE     24

#define LAND_NEAR_THIN_FACTOR	1
#define LAND_MIDDLE_THIN_FACTOR 2
#define LAND_FAR_THIN_FACTOR	4

#define LAND_TEXTURES_LAMBDA_MULT_FACTOR 4.0f

// Distance from viewer for change detail level
#define LAND_RANGE_NEAR_VIEW	0.0f
#define LAND_RANGE_MIDDLE_VIEW	15000.0f
#define LAND_RANGE_FAR_VIEW		20000.0f
#define LAND_RANGE_LIMIT_VIEW	1500000.0f

#define LAND_FOREST 0
#define LAND_RIVER  1
#define LAND_MUD    2

#define NUM_MAP_COLS 44
#define MAX_HEIGTH   5000.0f

#define GRASS_STATE 0
#define STONES_STATE 1
#define ROCKS_STATE  2
#define SNOW_STATE   3

#define ROCK_GROUND 0
#define SNOW_GROUND 1

// Color zones limits
#define LAND_LOW_PLAINS_COLOR		1//250.0f
#define LAND_HIGH_PLAINS_COLOR		2//500.0f
#define LAND_LOW_HILLS_COLOR		3//700.0f
#define LAND_HIGH_HILLS_COLOR		4//900.0f
#define LAND_MOUNTAINS_COLOR		5//1000.0f
#define LAND_SNOWY_MOUNTAINS_COLOUR	6//1100.0f

#define LAND_DARKESTGREEN			0.1f, 0.5f, 0.0f, 1.0f      
#define	LAND_DARKGREEN				0.2f, 0.5f, 0.1f, 1.0f		 
#define LAND_OLIVEBROWN             0.3f, 0.5f, 0.2f, 1.0f      
#define	LAND_BROWNGREEN				0.2f, 0.5f, 0.2f, 1.0f      
#define	LAND_GRAYGREEN				0.3f, 0.5f, 0.3f, 1.0f      
#define	LAND_STONEGRAY				0.5f, 0.7f, 0.6f, 1.0f		 
#define	LAND_HIGHICE				0.84f, 0.94f, 0.96f, 1.0f   

#define LAND_MIN_INCLINATION_FOR_ROCKS 0.6
#define LAND_MIN_INCLINATION_FOR_HILLS 0.4

#define LAND_RED   1.0f,0.0f,0.0f,1.0f
#define LAND_BLUE  0.0f,0.0f,1.0f,1.0f

#define LAND_DARK  0.30f,0.70f,0.20f,1.0f
#define LAND_DARK1 0.27f,0.70f,0.17f,1.0f
#define LAND_DARK2 0.25f,0.70f,0.15f,1.0f
#define LAND_DARK3 0.27f,0.67f,0.17f,1.0f

#define LAND_GRAY  0.369f,0.345f,0.504f,1.0f
#define LAND_GRAY1 0.390f,0.370f,0.500f,1.0f
#define LAND_GRAY2 0.350f,0.356f,0.455f,1.0f
#define LAND_GRAY3 0.300f,0.300f,0.403f,1.0f

#define LAND_GREEN  0.20f,0.60f,0.10f,1.0f
#define LAND_GREEN1 0.17f,0.60f,0.07f,1.0f
#define LAND_GREEN2 0.15f,0.60f,0.05f,1.0f
#define LAND_GREEN3 0.17f,0.57f,0.07f,1.0f

#define LAND_WHITE 1.0f,1.0f,1.0f,1.0f
#define LAND_ICE   0.84f,0.94f,0.96f,1.0f

#define NORTH 0
#define EAST  1
#define SOUTH 2
#define WEST  3

//#define LAND_TEXTURES_PATH "./bumpnoise.rgb"

#define resetNormalMatrix(p,r,c,i,j); for(int i = 0; i < r; i++) for(int j = 0; j < c ; j++) sgZeroVec3(*p[i][j]);
#define interpolateNormal(on,x,y,nn); /*sgNormaliseVec3(nn);*/ sgAddVec3(on[x][y],nn); //sgNormaliseVec3(on[x][y]);

static int wire_draw(ssgEntity* e);
static void wire_update(ssgEntity *e, int flag);

class Land  
{
public:
	Land(char dem_filename[],char obj_filename[], LoadingInfo* li);
	virtual ~Land();

	//to get the node
	ssgTransform* getTransform();
	ssgTransform* getRepositionTransform();

	float getStartE();
	float getStartN();

	float*** getLevelsMatrix();
	float*** getExpoMatrix();
	float*** getColorsMatrix();
	float*** getShadowMatrix();
	int getHeigth();
	int getWidth();

	void freeAllMatrix();

	float getXCorrection();
	float getYCorrection();

	void setWireframe(int s);

	ssgSimpleState* getState(int type);

	void addWorld(char filename[]);

	float reposition(Land *l,int where, float y);

private:
	// Data map 
	char dem_filename[LAND_FILENAME_STRING_LENGTH];		//DEM (or XYZ) file name
	char obj_filename[LAND_FILENAME_STRING_LENGTH];
	sgFloat **landMap;								//height data matrix
	sgFloat **worldMap;								//world heigth data matrix
	int mapRows;									//matrix row number
	int mapCols;									//matrix column number
	int x_start_coord;								//map x (c) start East coord
	int y_start_coord;								//map y (r) start North coord
	int gridStep;									//grid step (in meters)
	int gridThinFactor;								//grid thin factor
	sgFloat max;									//terrain max height
	sgFloat min;									//terrain min height 

	int triangle_grid_size;							// number of squares per side in each leaf
	int tile_size;									// leaves side dimension 

	int exceeding_r;
	int exceeding_c;

	int tile_grid_columns ;						// number of leaves along x
	int tile_grid_rows ;						// number of leaves along y

	float online_terrain_range_x ;					// center point (x) of the terrain (if it's bottom left corner lies over the origin)
	float online_terrain_range_y ;					// center point (y) of the terrain (if it's bottom left corner lies over the origin)

	sgFloat lambda;									// lambda factor for textures
	sgFloat lambda_r,lambda_c;

	int tile_grid_number_x ;
	int tile_grid_number_y ;

	// land transform node
	ssgTransform *landTransform;
	ssgTransform *terrainRecenteringTransform;

	// tile grid nodes matrix
	ssgTransform ***tileGrid;

	// methods used to create the sub-sectors and the leaves of the map
	void buildTerrain();
	void tryBuildTerrain();

	void fillAllMatrix();
	void createTiles();
	ssgBranch* createTileAt(int y, int x);
	ssgBranch* createLODTilesAt(int y, int x);
	ssgBranch* createTilePortion(int x, int y, int th, float z_down);

	// 
	float* getHeigthColor(float h);
	void createColorMatrix(float ***colors, float ***normals);

	//ssgSimpleState *state;
	ssgSimpleState *grass_state;
	ssgSimpleState *stones_state;

	void createStates();

	int saveColorMatrix(float ***cm);
	GLubyte* createPrintableMap(float*** cm);
	void createBitmapMatrix(float ***bm);
	void createExpositionMatrix(float ***bm,float ***n);
	int saveExpositionMatrix(float ***em);
	void createShadowMatrix(float ***c, float ***n);

	BMPImage* bmp;

	int loadObjectFile(float*** cm);
	void loadObjects(float*** cm, GLubyte *bits);
	
	

	// Matrices
	float ***objects;
	float ***bitmap;
	float ***colors;
	float ***normals;
	float ***expo;
	float ***shadow;

	LoadingInfo *li;
};
#endif // !defined(LAND_H)
